package org.cainiao.basic.inherit.test1;

/**
 * <br />
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
public class InheritTest {

    public static void main(String[] args) {
        Child child = new Child();
        /*
         * 打印的 "Child"
         * Child 类没有 doTestOverride() 方法，调用的是 Parent 的 doTestOverride()
         * 虽然 Parent 中调用的 this.testOverride(); 加了 this 关键字
         * 但调用的仍然是被 Child 重写的 testOverride() 方法
         */
        child.doTestOverride();
        /*
         * 打印的 "Ancestor super"
         * Child 类没有 doTestSuper() 方法，调用的是 Parent 的 doTestSuper()
         * Parent 中调用的 super.testSuper(); 加了 super 关键字
         * 虽然 Child 重写的 testSuper() 方法，但仍然调用的 Parent 的父类 Ancestor 的 testSuper() 方法
         * 说明与 this 关键字不同，super 关键字不会受到子类重写的影响
         */
        child.doTestSuper();
        /*
         * child 没有 message 字段，child.message 会访问父类 Parent 的 message 字段
         * 而 Parent 的 message 字段是 private 的，因此 child.message 编译时报错
         * 虽然 Ancestor 的 message 字段是 public 的，但在这个场景被 Parent 重写了
         * 也就是说，字段重写是可以让访问权限变小的
         *
         * 而 test(c) 与 test(new Parent()) 运行时没有报错，打印的都是 it's a
         * 说明虽然传入的是 C 对象或 Parent 对象
         * 并且 Parent 对象的 message 字段确实重写了 Ancestor 的 message 字段，在编译时会用 Parent 的 message 字段的访问权限来校验
         * 但在运行时，a.message 取的却是 Ancestor 的 message 字段
         * 这一点对于 public 的 type 仍然成立
         * 说明这个特性与访问权限无关，a.type 这种写法取哪个字段，不会考虑子类重写，而是按照声明类型来获取的对象字段值
         * 就连强转类型的 ((Ancestor) c).type 获取到的都是 "it's a type"
         * 这一点与方法重写是不同的
         * 例如对于 test(c);，a.getType() 打印的是 it's b type
         * 这是因为调用的是 C 重写的 getType() 方法，而 C 中的 this.type 是 Parent 的 type
         *
         * C 中定义 getMessage() 方法会编译时报错，因为 C 中的 this.message 会与 c.message 一样
         * 由于 Parent 重写的 message 为 private 而屏蔽掉了 Ancestor 的 message
         */
        // System.out.println(child.message);
        System.out.println(child.type);
        System.out.println(((Ancestor) child).type);
        System.out.println();

        test(child);
        test(new Parent());

        System.out.println();
        System.out.println(child.getName());
    }

    private static void test(Ancestor ancestor) {
        System.out.println(ancestor.message);
        System.out.println(ancestor.type);
        System.out.println(ancestor.getType());
        System.out.println();
    }

}
